/*
 * forktest.c
 *
 *  Created on: Jun 18, 2011
 *      Author: peckb1
 */

#include "syscall.h"
#include "usercommon.h"

static int numberOfTimesForked;
static int numberOfTimesDoubleForked;
static int threadCounterLock;
static int threadDoubleCounterLock;

void ThreadToDoubleFork() {

    Acquire(threadDoubleCounterLock);
    printf_3("I'm the thread to double fork, we have been spawned ", numberOfTimesDoubleForked, " times.\n");
    Release(threadDoubleCounterLock);

    Exit(0);
}

int i;
void ThreadToFork() {

    Acquire(threadCounterLock);
    printf_3("I'm the thread to fork, we have been spawned ", numberOfTimesForked, " times.\n");

    Acquire(threadDoubleCounterLock);
    for(i = 0; i < 2; i++) {
        numberOfTimesDoubleForked++;
        Release(threadDoubleCounterLock);
        Fork("Thread To Double Fork", 21, ThreadToDoubleFork);
        Yield();
        Acquire(threadDoubleCounterLock);
    }
    Release(threadDoubleCounterLock);


    Release(threadCounterLock);
    Exit(0);
}

int
main() {
    printLock = CreateLock("Printing Lock");

    numberOfTimesForked = 0;

    threadCounterLock = CreateLock("Fork Thread Lock");
    threadDoubleCounterLock = CreateLock("Double Fork Thread Lock");

    Acquire(threadCounterLock);
    while(numberOfTimesForked < 100) {
        numberOfTimesForked++;
        Release(threadCounterLock);
        Fork("Thread To Fork", 14, ThreadToFork);
        Yield();
        Acquire(threadCounterLock);
    }

    Release(threadCounterLock);


    /*
     * Note: cannot fork to a thread that doesn't exist as it would actually not compile
     */



    Exit(0);
}
